#include "log.h"
#include "gerror.h"
#include <Python.h>
#include <sstream>

using namespace std;

#define PY_FORMAT_MODULE "logformatter"
#define PY_NOW_FUNC	"now"

Log::Log() :
		progressStr(""), progressCur(-1), appending(false), output(cerr)
{
}

void Log::init()
{
	PyObject *pModule;
	pModule = PyImport_ImportModule(PY_FORMAT_MODULE);
	pythonError(pModule, PYERR_MODULE(PY_FORMAT_MODULE));

	pNow = PyObject_GetAttrString(pModule, PY_NOW_FUNC);
	pythonError(pNow, PYERR_ATTR(PY_NOW_FUNC));
	Py_DECREF(pModule);
}

string Log::now()
{
	if (pNow != NULL)
	{
		PyObject *pStr = PyObject_CallObject(pNow, NULL);
		pythonError(pStr, PYERR_FUNC(PY_NOW_FUNC));
		const char *str = PyString_AsString(pStr);
		return string(str) + " ";
	}
	else
		return string("");
}

void Log::reset()
{
	progressCur = -1;
	progressStr = "";
	if (appending)
	{
		appending = false;
		output << endl;
	}
}

void Log::error(exception &e)
{
	error(e.what());
}

void Log::error(string msg)
{
	reset();
	output << now() << "ERROR " << msg << endl;
}

void Log::debug(string desc, string msg)
{
	if (!debugMode)
		return;
	reset();
	output << now() << "DEBUG " << desc << endl << msg;
}

void Log::info(std::string msg, bool p)
{
	if (!verbose)
		return;
	reset();
	output << now() << "INFO " << msg;
	if (p)
		progress(0);
	appending = (msg[msg.length() - 1] != '\n') ? true : false;
}

void Log::progress(double x, double total)
{
	if (!verbose || progressCur >= 100)
		return;
	int p = (int) (x * 100 / total);
	if (p <= progressCur)
		return;
	if (p > 100)
		p = 100;
	for (unsigned int i = 0; i < progressStr.length(); i++)
		output << '\b';
	ostringstream ss;
	ss << p << '%';
	progressStr = ss.str();
	progressCur = p;
	output << progressStr;
	appending = true;
}

void Log::append(string msg)
{
	if (!verbose)
		return;
	output << msg;
	appending = (msg[msg.length() - 1] != '\n') ? true : false;
}

Log logger;
